﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;

namespace AsyncNetworkTransfer
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        Socket server;
        private byte[] data = new byte[1024];
        private int size = 1024;
        int port = 9050;
        private ListBox results;
        List<Socket> clients = new List<Socket>();
        private void button1_Click(object sender, EventArgs e)
        {
            textBox1.Text += "Starting Server..." + Environment.NewLine;
            server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint iep = new IPEndPoint(IPAddress.Any, 9050);
            server.Bind(iep);
            server.Listen(5);
            server.BeginAccept(new AsyncCallback(AcceptConn), server);
            textBox1.Text += "Server Started." + Environment.NewLine;
        }

        void AcceptConn(IAsyncResult iar)
        {
            Socket oldserver = (Socket)iar.AsyncState;
            Socket client = oldserver.EndAccept(iar);
            clients.Add(client);
            AddText("Connected to: " + client.RemoteEndPoint.ToString());
            string stringData = "Welcome to my server";
            byte[] message1 = Encoding.ASCII.GetBytes(stringData);
            client.BeginSend(message1, 0, message1.Length, SocketFlags.None,
                  new AsyncCallback(SendData), client);
            server.BeginAccept(new AsyncCallback(AcceptConn), server);
        }

        void SendData(IAsyncResult iar)
        {
            Socket client = (Socket)iar.AsyncState;
            int sent = client.EndSend(iar);
            client.BeginReceive(data, 0, size, SocketFlags.None,
                  new AsyncCallback(ReceiveData), client);
        }

        private delegate void AddTextBoxItemDelegate(object item);
        void ReceiveData(IAsyncResult iar)
        {
            Socket client = (Socket)iar.AsyncState;
            int recv = client.EndReceive(iar);
            if (recv == 0)
            {
                client.Close();
                server.BeginAccept(new AsyncCallback(AcceptConn), server);
                return;
            }
            string receivedData = Encoding.ASCII.GetString(data, 0, recv);
            AddText(receivedData);
            client.BeginReceive(data, 0, size, SocketFlags.None, new AsyncCallback(ReceiveData), client);
        }

        private delegate void AddTextDelegate(object item);
        private void AddText(object item)
        {
            if (this.textBox1.InvokeRequired)
            {   
                this.textBox1.Invoke(new AddTextDelegate(this.AddText), item); 
            }
            else {  
                this.textBox1.Text += item.ToString() + Environment.NewLine;            
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
        }

        private void button2_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < clients.Count; i++)
            {
                Socket client = clients[i];
                byte[] message = Encoding.ASCII.GetBytes("Message");
                client.BeginSend(message, 0, message.Length, SocketFlags.None,
                       new AsyncCallback(SendData), client);
                message = Encoding.ASCII.GetBytes("Server : " + textBox2.Text);
                client.BeginSend(message, 0, message.Length, SocketFlags.None,
                        new AsyncCallback(SendData), client);
            }
            textBox2.Clear();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            openFileDialog1.ShowDialog();
            string filename = Path.GetFileName(openFileDialog1.FileName);
            string fileLocation = openFileDialog1.FileName;

            for (int i = 0; i < clients.Count; i++)
            {
                Socket client = clients[i];
                //Send Command
                byte[] message = Encoding.ASCII.GetBytes("File");
                client.BeginSend(message, 0, 4, SocketFlags.None,
                       null, client);

                //Send File Name
                message = Encoding.ASCII.GetBytes(filename);
                client.BeginSend(message, 0, filename.Length, SocketFlags.None,
                        null, client);

                //Send File Length
                FileStream stream = File.Open(fileLocation, FileMode.Open);
                message = Encoding.ASCII.GetBytes(stream.Length.ToString());
                client.BeginSend(message, 0, stream.Length.ToString().Length, SocketFlags.None,
                        null, client);

                //Begin Data Send
                byte[] data = new byte[1024];
                long sent = 0;
                long totalSize = stream.Length;
                while (sent < totalSize)
                {
                    int a = 1024;
                    for (int j = 0; j < 1024; j++)
                        if (stream.CanRead)
                        {
                            sent++;
                            data[j] = (byte)stream.ReadByte();
                        }
                        else
                        {
                            a = j;
                            break;
                        }
                    client.BeginSend(data, 0, a, SocketFlags.None, null, client);
                }
                stream.Close();
                message = Encoding.ASCII.GetBytes(sent.ToString());
                client.BeginSend(data, 0, data.Length, SocketFlags.None, null, client);
            }
        }
    }
}
